home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
VANESSA.C
< prev
next >
Wrap
Text File
|
1993-08-09
|
11KB
|
358 lines
/* Vanessa Board Interface, 7.1.92
* implemented by Marcel Wiget, HB9RWM
* for NOS (Copyright 1991 Phil Karn, KA9Q)
*
* Vanessa is part of the project SEPRAN,
* Swiss Experimental Packet Radio Amateur Network,
* of the SWISS-ARTG (Swiss Amateur Radio Teleprinter Group).
* The full-size XT-Board contains 2 seperate interfaces
* for high-speed AX.25 Layer-2 data streams. The data
* can be received and sent via Dual-Port RAM embedded in a
* KISS - Frame. Result: very less overhead for NOS to receive
* and send a frame (e.g. only 1 memcpy for the hole frame).
*
* 10.11.91: Support of Vanessa Version 3.0 (word allignement RAM)
* param command support
* statistic support (e.g. if va0)
* 14.11.91: set of Node ID and Alias
* safe waiting for cmd completion
* 19.11.91: info for 2nd port was wrong
* 20.11.91: download added
* 21.11.91: statistics for port 1 corrected, mbuf handling
* 17.11.91: some adaptions made for use with WNOS - DB3FL
* 24.11.91: dirps() and restore() inserted to mask interrupts
* and changed buffer allocations and statistics
* 'param'-command adapted to WNOS strategy
* 7.01.92: if_param no longer supported by wnos, removed.
*/
#include <stdio.h>
#include <dos.h> /* for MK_FP */
#include "global.h"
#include "config.h"
#ifdef VANESSA
#include "proc.h"
#include "commands.h"
#include "mbuf.h"
#include "ax25.h"
#include "ip.h" /* def. Ip_Addr */
#include "pktdrvr.h" /* def. for CL_AX25 */
#include "trace.h"
#include "vanessa.h"
static struct vandrvr Vandrvr[VAN_MAX];
static int van_stop __ARGS((struct iface *iface,int temp));
/* Attach a Vanessa interface to the system
* One board has 2 interfaces (Port 0 and 1)
* Each Port must have its own interface,
* attached via different dpram_base (dual port ram base address)
* argv[0]: hardware type, must be "vanessa"
* argv[1]: interface label, e.g., "va0"
* argv[2]: port-nr, started with 0,1: board 0, with 2,3: board 1 etc.
* argv[3]: maximum transmission unit, bytes (MTU) (optional)
*/
int
van_attach(int argc,char **argv,void *p)
{
struct iface *ifvan;
struct vandrvr *vp;
struct dp_record far *dp;
unsigned char *cp;
int i;
if(if_lookup(argv[1]) != NULLIF){
tprintf(Ifexist,argv[1]);
return -1;
}
if(*Mycall == '\0') { /* better to be sure */
tputs(Nomycall);
return -1;
}
for (i = 0; i < VAN_MAX; i++){
if(Vandrvr[i].iface == NULLIF)
break;
}
if (i >= VAN_MAX){
tprintf("Max %d Vanessa drivers\n",VAN_MAX);
return -1;
}
/* Create interface structure and fill in details */
ifvan = mxallocw(sizeof(struct iface));
ifvan->addr = Ip_addr;
ifvan->name = strxdup(argv[1]);
ifvan->mtu = (4 == argc) ? atoi(argv[3]) : 256;
setencap(ifvan,"AX25");
ifvan->ioctl = van_ioctl;
ifvan->status = van_status;
ifvan->raw = van_raw;
ifvan->stop = van_stop;
ifvan->hwaddr = strxdup(Mycall);
ifvan->dev = i;
vp = &Vandrvr[i];
vp->portnr = htoi(argv[2]);
vp->dpram_base = MK_FP(BASE_SEGMENT + (vp->portnr << 8),0);
vp->ioled = BASE_IO + (vp->portnr & 1) + (vp->portnr >> 1)*8 + 6;
vp->iores = BASE_IO + (vp->portnr >> 1)*8;
vp->iface = ifvan;
van_reset(vp);
/* if port 0 of selected board, then */
/* set Node ID etc. */
dp = vp->dpram_base;
if (0 == (vp->portnr & 1)) {
/* ok, let's do it */
cp = (unsigned char *)(dp->dp_cData);
memcpy(cp,Mycall,AXALEN); /* MY_ID */
cp += AXALEN;
memcpy(cp,Mycall,AXALEN); /* MY_ALIAS */
cp += AXALEN;
*cp = (0xff & vp->portnr);
dp->dp_cCMD = CMD_ID_LOAD;
}
outportb(vp->ioled,LED_OFF);
/* init statistics */
vp->nTXwait = 0;
vp->nRXmaxlen = 0;
vp->nTXmaxlen = 0;
init_maxheard(ifvan);
init_flags(ifvan);
ifvan->proc = newproc("van rx",256,van_rx,ifvan->dev,NULL,NULL,0);
/* Link in the interface */
ifvan->next = Ifaces;
ifvan->niface = Niface++; /* WNOS router */
Ifaces = ifvan;
return 0;
}
/* van_ioctl:
* perform device control on VANESSA KISS
*/
static int
van_ioctl(struct iface *iface,int argc,char **argv)
{
struct vandrvr *vp = &Vandrvr[iface->dev];
struct dp_record far *p = vp->dpram_base;
int pn = 0, v, i;
if (2 == argc) {
/* set value */
pn = atoi(argv[0]); /* param-nr to change */
v = (int16)atoi(argv[1]); /* value to be loaded */
}
for(i = 1;i < PARAM_COUNT; i++) {
switch(i) {
case TXDELAY:
if (i==pn) {
p->dp_pTXDelay = v;
} else {
tprintf("TxDelay %d\n", p->dp_pTXDelay);
}
break;
case PERSIST:
if (i==pn) {
p->dp_pPersist = v;
} else {
tprintf("Persistence %d\n", p->dp_pPersist);
}
break;
case SLOTTIME:
if (i==pn) {
p->dp_pSlottime = v;
} else {
tprintf("SlotTime %d\n", p->dp_pSlottime);
}
break;
case TXTAIL:
if (i==pn) {
p->dp_pTXTail = v;
} else {
tprintf("TxTail %d\n", p->dp_pTXTail);
}
break;
case FULLDUP:
if (i==pn) {
p->dp_pDuplex = v;
} else {
tprintf("Fullduplex %d\n", p->dp_pDuplex);
}
break;
default:
break;
}
if (pn){
p->dp_reReadPar = 0;
}
}
return 0;
}
/* send raw data packet on KISS VANESSA */
static int
van_raw(struct iface *iface,struct mbuf *data)
{
struct vandrvr *vp;
struct dp_record far *p;
int16 len = len_p(data);
int i_state;
if (0 < len) {
vp = &Vandrvr[iface->dev];
dump(iface,IF_TRACE_OUT,CL_AX25,data);
p = vp->dpram_base;
if (0 == p->dp_oFProd)
vp->nTXwait++;
while ( (NULLIF != vp->iface) && (0 == p->dp_oFProd) ) {
/* still busy, should not happen */
pwait(NULL);
}
if (NULLIF != vp->iface) {
/* send it */
i_state = dirps();
p->dp_oLFrm = len;
len = dqdata(data,(char *)&p->dp_oBuffer[0],len);
if (len > vp->nTXmaxlen)
vp->nTXmaxlen = len;
p->dp_oFProd = 0; /* send it */
restore(i_state);
}
} else
free_p(data);
return 0;
}
static void
van_rx(int dev,void *p1,void *p2)
{
struct vandrvr *vp = &Vandrvr[dev];
struct mbuf *rcvbuf;
struct phdr phdr;
struct dp_record far *p = vp->dpram_base;
char *cp;
int16 len;
int i_state;
while (vp->iface != NULLIF){
if (0 == p->dp_iFProd) {
/* data arrived */
len = p->dp_iLFrm;
if (len > vp->nRXmaxlen)
vp->nRXmaxlen = len;
if (len > 0) {
i_state = dirps();
outportb(vp->ioled,LED_ON);
rcvbuf = alloc_mbuf(len + sizeof(struct phdr));
cp = rcvbuf->data + sizeof(struct phdr);
memcpy(cp,(char *)&p->dp_iBuffer[0],len);
rcvbuf->cnt = sizeof(struct phdr) + len;
rcvbuf->next = NULLBUF;
phdr.iface = vp->iface;
phdr.type = CL_AX25;
memcpy(rcvbuf->data,(char *)&phdr,sizeof(struct phdr));
restore(i_state);
enqueue(&Hopper,rcvbuf);
}
outportb(vp->ioled,LED_OFF);
p->dp_iFProd = 1; /* open DPRAM for next frame */
}
pwait(NULL);
}
}
/* shut down the VANESSA interface */
static int
van_stop(struct iface *iface,int temp)
{
struct vandrvr *vp = &Vandrvr[iface->dev];
if (NULLIF != vp->iface) {
vp->iface = NULLIF;
}
return 0;
}
static void
van_reset(struct vandrvr *vp)
{
outportb(vp->iores,0xff);
pwait(NULL);
outportb(vp->iores,0);
}
static int32
cova(char *p,int16 n)
{
int i;
int32 rv = 0;
n--;
for (i=n;i>=0;i--) rv = (rv<<8)+(p[i]&0xff);
return rv;
}
/* Show vanessa port status */
static int
van_status(struct iface *iface)
{
struct vandrvr *vp = &Vandrvr[iface->dev];
struct dp_record far *dp0 =
MK_FP(FP_SEG(vp->dpram_base)-((vp->portnr & 1)<<8),0);
struct dp_record far *dp1 =
MK_FP(FP_SEG(dp0)+0x0100,0);
if (NULLIF != vp->iface) {
int i = 0, i_state = dirps();
dp0->dp_cCMD = CMD_POINTER;
while (i < CMD_TIMEOUT && dp1->dp_cCMD != (CMD_POINTER | 0xf000)) {
i++;
pwait(NULL);
}
if (CMD_TIMEOUT == i) {
tputs("No valid data\n");
} else {
char *cp = (char *)dp1->dp_cData;
tprintf("\n Port %u: DP-RAM=%p TXwait=%u TXmaxlen=%u RXmaxlen=%u",
vp->portnr,
vp->dpram_base,
vp->nTXwait,
vp->nTXmaxlen,
vp->nRXmaxlen);
tprintf("\n SWrev=%x\.%02x Rst=%u Board=%u",
cp[cRev+1],
cp[cRev],
cova(&cp[cRst],2),
cp[cPNr] & 0xf);
cp += (vp->portnr&1 ? cPort1 : 0);
tprintf(" Counters: Rx=%lu Tx=%lu TxKu=%lu\n",
cova(&cp[cRx],3),
cova(&cp[cTx],3),
cova(&cp[cTxKu],3));
tprintf("\n RxBf TxBf RxBe TxBe RFlI TflC TFlI RCRC "
"RxOv TxTo SyTx SyRx RxAb TxUdr\n ");
for (i = cRxBf; i <= cTxUdr; i += 2)
tprintf("%5u",cova(&cp[i],2));
tputs("\n");
}
restore(i_state);
}
return 0;
}
#endif /* VANESSA */